package com.barney.support.image;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

/**
 * 타일 만들기<br/>
 *
 * @author Barney Kim
 */
public class MakeTile {

	private static final Logger log = LoggerFactory.getLogger(MakeTile.class);

	private static final int TILE_SIZE = 256;

	private final static String TILE_NAME_FORMAT = "%d_%d.%s";

	private int tileSize = TILE_SIZE;

	private String sourcePath;

	private String destPath;

	private String tileNameFormat = TILE_NAME_FORMAT;

	private int startX = 0;
	private int startY = 0;

	/**
	 * 타일 크기를 설정한다.
	 */
	public void setTileSize(int tileSize) {
		this.tileSize = tileSize;
	}

	/**
	 * 원본 이미지 소스 패스를 설정한다.
	 */
	public void setSourcePath(String sourcePath) {
		this.sourcePath = sourcePath;
	}

	/**
	 * 타일이 생성될 패스를 설정한다.
	 */
	public void setDestPath(String destPath) {
		this.destPath = destPath;
	}

	/**
	 * 타일 명 형식을 설정한다.
	 *
	 * @param tileNameFormat
	 */
	public void setTileNameFormat(String tileNameFormat) {
		this.tileNameFormat = tileNameFormat;
	}

	/**
	 * 시작 X를 설정한다.
	 */
	public void setStartX(int startX) {
		this.startX = startX;
	}

	/**
	 * 시작 Y를 설정한다.
	 */
	public void setStartY(int startY) {
		this.startY = startY;
	}

	/**
	 * 타일을 만든다.
	 *
	 * @throws IOException
	 */
	public void makeTile() throws IOException {
		Assert.notNull(sourcePath, "sourcePath required");
		File sourceFile = new File(sourcePath);
		Assert.isTrue(sourceFile.exists(), "Source '" + sourcePath + "' NOT found.");
		String fileType = null;
		if (sourceFile.getName().endsWith(".png")) {
			fileType = "png";
		} else {
			fileType = "jpg";
		}
		if (destPath == null) {
			destPath = sourceFile.getParent();
		}
		File destDir = new File(destPath);
		if (!destDir.exists()) {
			FileUtils.forceMkdir(destDir);
		}

		BufferedImage img = ImageIO.read(new FileInputStream(sourceFile));

		int xZero = img.getWidth() / (tileSize * 2) * 16;
		int yZero = xZero - 1;
		int xSlice = img.getWidth() / tileSize;
		int ySlice = img.getHeight() / tileSize;
		if ((img.getWidth() % tileSize) != 0) {
			xSlice++;
		}
		if ((img.getHeight() % tileSize) != 0) {
			ySlice++;
		}
		int ybm = (tileSize * ySlice) - img.getHeight();
		int xp = xZero;
		int yp = yZero - (ySlice - 1);

		log.debug("src={}, xSlice={}, ySlice={}, xp={}, yp={}",
				new Object[] { sourceFile.getAbsolutePath(), xSlice, ySlice, xp, yp });

		int tileCount = 0;
		for (int i = 0; i < xSlice; i++) {
			for (int j = 0; j < ySlice; j++) {
				int x = i * tileSize;
				int y = (j * tileSize) - ybm;

				GraphicsConfiguration gc = img.createGraphics().getDeviceConfiguration();
				BufferedImage tile = null;
				if (fileType.equals("png")) {
					tile = gc.createCompatibleImage(tileSize, tileSize, Transparency.BITMASK);
				} else {
					tile = gc.createCompatibleImage(tileSize, tileSize, Transparency.BITMASK);
					// tile = gc.createCompatibleImage(tileSize, tileSize);
				}
				Graphics2D g = tile.createGraphics();
				g.drawImage(img, -x, -y, Color.GRAY, null);
				int fileX = startX + i;
				int fileY = startY + j;
				File df = new File(destDir, String.format(tileNameFormat, (fileX + xp),
						(fileY + yp), fileType));
				if (df.exists()) {
					df.delete();
				}
				ImageIO.write(tile, fileType, df);
				log.debug("tile={},x={},y={}", new Object[] { df.getAbsolutePath(), x, y });
				tileCount++;
			}
		}
		log.debug("tile count={}", tileCount);
	}
}
